package kuzmenkov.oip.service.impl;

import kuzmenkov.oip.common.I18nTool;
import kuzmenkov.oip.model.Comment;
import kuzmenkov.oip.model.Module;
import kuzmenkov.oip.model.User;
import kuzmenkov.oip.model.dao.hibernate.CommentDao;
import kuzmenkov.oip.model.dao.hibernate.UserDao;
import kuzmenkov.oip.service.CommentService;
import kuzmenkov.oip.service.ModuleChoosingService;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.logging.Logger;

/**
 * @see kuzmenkov.oip.service.CommentService
 *      User: Michael Kuzmenkov
 *      Date: 27.03.2009
 *      Time: 15:25:23
 */
public class CommentServiceImpl implements CommentService {
    private final static Logger log = Logger.getLogger(CommentServiceImpl.class.getName());

    private ModuleChoosingService moduleChoosingService;

    private UserDao userDao;
    private CommentDao commentDao;

    private List<CommentItem> commentItems;
    private List<Chunk> chunks;
    private int currentChunkIndex = 0;
    private final static int MAX_QUANTITY_OF_COMMENTS = 10;
    private boolean isChunking = false;

    private I18nTool i18nTool;

    public void setI18nTool(I18nTool i18nTool) {
        this.i18nTool = i18nTool;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void setCommentDao(CommentDao commentDao) {
        this.commentDao = commentDao;
    }

    public void setModuleChoosingService(ModuleChoosingService moduleChoosingService) {
        this.moduleChoosingService = moduleChoosingService;
    }

    public String getModuleName() throws Exception {
        return moduleChoosingService.getModuleName();
    }

    public List<CommentItem> getCommentItems() throws Exception {
        List<CommentItem> items = null;
        try {
            if (!isChunking)
                this.commentItems = createCommentItemList();

            this.isChunking = false;
            Chunk currentChunk = chunks.get(this.currentChunkIndex);
            items = this.commentItems.subList(currentChunk.getBeginIndex(), currentChunk.getEndIndex());
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage("CommentServiceImpl.gettingCommentItems"));
        }
        return items;
    }

    private List<CommentItem> createCommentItemList() {
        Module module = moduleChoosingService.getCurrentModule();
        Set<Comment> comments = module.getComments();

        List<CommentItem> commentItems = new ArrayList<CommentItem>(comments.size());

        for (Comment comment : comments) {

            User user = comment.getUser();
            String userName = user.getName();
            String email = user.getEmail();

            Timestamp sendingDate = comment.getSendingDate();
            log.info("sendingDate=" + sendingDate);
            Locale locale = getLocale();
            DateFormat dateIns = DateFormat.getDateInstance(DateFormat.LONG, locale);
            DateFormat timeIns = DateFormat.getTimeInstance(DateFormat.MEDIUM, locale);
            String strSendDate = dateIns.format(sendingDate) + " " + timeIns.format(sendingDate);

            String message = comment.getMessage();


            CommentItem commentItem = new CommentItem(userName, email, strSendDate, message);
            commentItems.add(commentItem);
        }
        initChunking(commentItems.size());
        return commentItems;
    }

    private void initChunking(int commQuant) {
        if (commQuant<=0)
                throw new IllegalArgumentException("Quatity of comments is not legal");
        // chunking comments

        int quantityOfChunks = commQuant / MAX_QUANTITY_OF_COMMENTS;
        if (commQuant % MAX_QUANTITY_OF_COMMENTS != 0 || commQuant == 0)
            quantityOfChunks++;
        this.chunks = new ArrayList<Chunk>(quantityOfChunks);
        this.currentChunkIndex = quantityOfChunks - 1;
        for (int i = 0; i < quantityOfChunks; i++) {
            int begIndex = i * MAX_QUANTITY_OF_COMMENTS;
            int endIndex = begIndex + MAX_QUANTITY_OF_COMMENTS;
            if (endIndex > commQuant) {
                endIndex = commQuant;
            }
            Chunk ch = new Chunk((i + 1), begIndex, endIndex);
            chunks.add(ch);

        }

    }

    public void chunking(int number) {
        this.isChunking = true;
        this.currentChunkIndex = number;
    }

    public List<Chunk> getChunks() {

        return chunks;
    }

    public void storeComment(String userName, String email, String message) throws Exception {
        try {
            List<User> users = userDao.findByEmail(email);
            if (users.size() > 1) {
                log.warning(users.size() + " users have the same email: " + email);
            }
            Module module = moduleChoosingService.getCurrentModule();
            User user = null;
            if (users.size() == 0) {
                log.info("Creating new user: name=" + userName + ", email=" + email);
                user = new User();
                user.setName(userName);
                user.setEmail(email);
                userDao.create(user);
            } else {
                log.info("Getting user " + userName);
                user = users.get(0);

                //if (!user.getName().equals(userName)){
                //!! take a look with an attention
                //}
            }

            Comment comment = new Comment();

            comment.setMessage(message);

            comment.setUser(user);
            //user.getComments().add(comment);

            comment.setModule(module);

            Timestamp currTime = new Timestamp(System.currentTimeMillis());
            comment.setSendingDate(currTime);

            log.info("Creating new comment: user=" + userName + ", message=" + message);
            commentDao.create(comment);
            module.getComments().add(comment);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(i18nTool.getMessage("CommentServiceImpl.storingComment"));
        }
    }


    private Locale getLocale() {
        return i18nTool.getLocale();
    }

    public int getCurrentChunkIndex() {
        return currentChunkIndex;
    }
}